package com.wzapp.sitposture.common.error;

import com.wzapp.sitposture.common.exception.AuthenticationException;
import com.wzapp.sitposture.common.exception.AuthorizationException;
import com.wzapp.sitposture.common.exception.BadRequestException;
import com.wzapp.sitposture.common.exception.NotfoundException;
import com.wzapp.sitposture.common.util.ExceptionUtil;
import com.wzapp.sitposture.common.util.ResourceBundleUtil;
import org.apache.catalina.connector.ClientAbortException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;

/**
 * Created by LiMaosheng on 2016/4/18.
 */
@ControllerAdvice
public class ExceptionAdvice {
    private static final Logger log = LoggerFactory.getLogger(ExceptionAdvice.class);

    @Autowired
    private ExceptionUtil eigExceptionUtil;

    @Autowired
    private ResourceBundleUtil resourceBundleUtil;

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseEntity exception(Throwable ex, HttpServletRequest request) throws CustomizedException {

        Throwable throwable = eigExceptionUtil.obtainThrowable(ex);

        HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
        ErrorMessage errorMessage = new ErrorMessage();

        String message = throwable.getMessage();
        errorMessage.setMessage(message);

        if (throwable instanceof CustomizedException) {
            httpStatus = HttpStatus.BAD_REQUEST;
            errorMessage.setCode(400000);
        } else if (throwable instanceof NotfoundException) {
            httpStatus = HttpStatus.NOT_FOUND;
            errorMessage.setCode(400000);
        } else if (throwable instanceof HttpRequestMethodNotSupportedException) {
            httpStatus = HttpStatus.NOT_FOUND;
            errorMessage.setCode(400000);
        } else if (throwable instanceof HttpMessageNotReadableException) {
            //参数异常
            httpStatus = HttpStatus.BAD_REQUEST;
            errorMessage.setCode(400000);
        } else if (throwable instanceof AsyncRequestTimeoutException) {
            //设置超时
            httpStatus = HttpStatus.BAD_GATEWAY;
            errorMessage.setCode(400000);
            errorMessage.setMessage("连接超时，请重新刷新webkey");
        } else if (throwable instanceof IllegalStateException) {
            //设置状态异常
            httpStatus = HttpStatus.BAD_REQUEST;
            errorMessage.setCode(400000);
            //获取授权超时
//            if (message.contains("ResponseBodyEmitter is already set complete")){
//            }
        } else if (throwable instanceof AccessDeniedException) {
            httpStatus = HttpStatus.FORBIDDEN;
            errorMessage.setCode(400000);
        } else if (throwable instanceof AuthorizationException) {
            httpStatus = HttpStatus.FORBIDDEN;
            errorMessage.setCode(400000);
        } else if (throwable instanceof AuthenticationException) {
            httpStatus = HttpStatus.UNAUTHORIZED;
            errorMessage.setCode(400000);
        } else if (throwable instanceof InvalidGrantException) {
            httpStatus = HttpStatus.UNAUTHORIZED;
            errorMessage.setCode(400000);
        } else if (throwable instanceof MethodArgumentNotValidException) {
            httpStatus = HttpStatus.BAD_REQUEST;
            errorMessage.setCode(400000);
            BindingResult bindingResult = ((MethodArgumentNotValidException) throwable).getBindingResult();
            List<ObjectError> allErrors = bindingResult.getAllErrors();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < allErrors.size(); i++) {
                ObjectError objectError = allErrors.get(i);
                sb.append(objectError.getDefaultMessage()).append(",");
            }
            sb.delete(sb.length() - 1, sb.length());
            errorMessage.setMessage(sb.toString());
        } else if (throwable instanceof ConstraintViolationException) {
            httpStatus = HttpStatus.BAD_REQUEST;
            errorMessage.setCode(400000);
        } else if (throwable instanceof HttpMediaTypeNotSupportedException) {
            httpStatus = HttpStatus.BAD_REQUEST;
            errorMessage.setCode(400000);
        } else if(throwable instanceof ClientAbortException){
            log.error("ClientAbortException:"+throwable.getMessage());
        } else {
            errorMessage.setCode(httpStatus.value());
            log.error("未知异常============"+ex);
            ex.printStackTrace();
        }

        if (throwable instanceof CustomizedException) {
            String[] args = ((CustomizedException) throwable).getArgs();
            resourceBundleUtil.parseErrorMessage(errorMessage, args, message);
        } else if (throwable instanceof BadRequestException) {
            String[] args = new String[]{};
            resourceBundleUtil.parseErrorMessage(errorMessage, args, errorMessage.getMessage());
        } else if (throwable instanceof NotfoundException) {
            String[] args = new String[]{};
            resourceBundleUtil.parseErrorMessage(errorMessage, args, errorMessage.getMessage());
        } else if (throwable instanceof AuthenticationException || throwable instanceof AuthorizationException){
            String[] args = new String[]{};
            resourceBundleUtil.parseErrorMessage(errorMessage, args, errorMessage.getMessage());
        } else if (throwable instanceof AccessDeniedException){
            //do noting
        }else {

        }

        return new ResponseEntity<>(errorMessage, httpStatus);
    }

}
